#include <brpc/server.h>
#include <butil/logging.h>
//实现语音识别子服务
#include "asr.hpp"      //语音识别封装
#include "etcd.hpp"     //服务注册
#include "logger.hpp"   //日志模块
#include "speech.pb.h"  //protobuf框架代码

namespace xchat{
//proto rpc SpeechService ; package xchat
class SpeechServiceImpl : public xchat::SpeechService
{
public:
    SpeechServiceImpl(const AsrClient::ptr &asr_client)
    :_asr_client(asr_client)
    {}
    ~SpeechServiceImpl(){}
    void SpeechRecognition(google::protobuf::RpcController* controller,
                        const ::xchat::SpeechRecognitionReq* request,
                        ::xchat::SpeechRecognitionRsp* response,
                        ::google::protobuf::Closure* done)
    {
        brpc::ClosureGuard rpc_guard(done);
        //1.取出请求中的语音数据
        //2.调用语音sdk模块进行语音识别 得到响应
        std::string err;
        std::string res = _asr_client->recognize(request->speech_content(), err);
        if(res.empty())
        {
            LOG_ERROR("{} 语音识别失败!", request->request_id());
            response->set_request_id(request->request_id());
            response->set_success(false);
            response->set_errmsg("语音识别失败:" + err);
            return;
        }
        //3.组织响应
        response->set_request_id(request->request_id());
        response->set_success(true);
        response->set_recognition_result(res);
    }
private:
    AsrClient::ptr _asr_client;
};
class SpeechServer
{
    public:
        using ptr = std::shared_ptr<SpeechServer>;
        SpeechServer(const AsrClient::ptr &asr_client, const Registry::ptr &reg_client, const std::shared_ptr<brpc::Server> &server)
        :_asr_client(asr_client)
        ,_reg_client(reg_client)
        ,_rpc_server(server)
        {}
        ~SpeechServer()
        {}

        //搭建rpc服务器 并启动服务器
        void start()
        {
            _rpc_server->RunUntilAskedToQuit();
        }
    private:
        AsrClient::ptr _asr_client; //语音识别sdk
        Registry::ptr _reg_client;  //注册中心
        std::shared_ptr<brpc::Server> _rpc_server;       //rpc服务
};
//建筑师模式
class SpeechServerBuilder
{
    public:
            //构造语音识别客户端对象
        void make_asr_object(const std::string &appid, const std::string &api_key, const std::string &secret_key)
        {
            _asr_client = std::make_shared<AsrClient>(appid, api_key, secret_key);

        }
        //用于构造服务注册客户端对象  服务中心地址 服务名称 当前实例的外部访问地址
        void make_reg_object(const std::string &reg_host, const std::string server_name, const std::string &access_host)
        {
            _reg_client = std::make_shared<Registry>(reg_host);
            _reg_client->registry(server_name, access_host);
        }
        void make_rpc_server(uint16_t port, uint32_t timeout, uint8_t num_threads)
        {
            if(!_asr_client)
            {
                LOG_ERROR("语音识别客户端对象未构造!");
                abort();
            }
            _rpc_server = std::make_shared<brpc::Server>();
            SpeechServiceImpl *speech_service = new SpeechServiceImpl(_asr_client); 
            int ret = _rpc_server->AddService(speech_service, brpc::ServiceOwnership::SERVER_OWNS_SERVICE);
            if(ret == -1)
            {
                LOG_ERROR("添加rpc服务失败!");
                abort();
            }
            brpc::ServerOptions options;
            options.idle_timeout_sec = timeout;  //连接空闲超时时间-超时后连接被关闭
            options.num_threads = num_threads;        //io线程数量
            //4.启动服务器
            ret = _rpc_server->Start(port, &options);
            if(ret == -1)
            {
                LOG_ERROR("启动rpc服务器失败!");
                abort();
            }

        }
        SpeechServer::ptr build()
        {
            //_rpc_server 构造前 其余的得构造好
            if(!_asr_client)
            {
                LOG_ERROR("语音识别客户端对象未构造!");
                abort();
            }
            if (!_reg_client)
            {
                LOG_ERROR("服务注册客户端对象未构造!");
                abort();
            }
            if(!_rpc_server)
            {
                LOG_ERROR("rpc服务对象未构造!");
                abort();
            }
            SpeechServer::ptr server = std::make_shared<SpeechServer>(_asr_client, _reg_client, _rpc_server);
            return server;
        }
    private:
        AsrClient::ptr _asr_client; //语音识别sdk
        Registry::ptr _reg_client;  //注册中心
        std::shared_ptr<brpc::Server> _rpc_server;       //rpc服务
};
}